"""
The default types for IOML must only allow the specified type to be set.

So, a [String] type can only be set to a string
an [Integer] type to an Integer, and so on


"""

from coffeetalk.protocol import ioelement

def _check_attributes(_setattr):
    
    def __setattr__(self,name,value):
        if hasattr(self,name):
            if type(self.__getattribute__(name)) == type(value):
                _setattr(self,name,value)
            else:
                raise AttributeError("Value must be of type %r. Got %r instead." % ((type(self.__getattribute__(name)).__name__),str(type(value).__name__)))
        elif name == 'type':
            pass
        else:
            raise AttributeError("Can't add attribute %r to %s" % (name,self))
    return __setattr__

class _AttrChecker(object):
    
    __setattr__ = _check_attributes(object.__setattr__)
    class __metaclass__(type):
        __setattr__ = _check_attributes(type.__setattr__)

class DefaultType(_AttrChecker):
    
    name=''
    def __init__(self,name=None,**kwargs):
        if name is None:
            name = self.__name__
        self.name = name
        
        for k,v in kwargs.iteritems():
            self.__setattr__(k,v)
    
    def __call__(self):
        if hasattr(self,'value'):
            return self.value
        
    def __str__(self):
        return str(self._to_element())

    def pretty_string(self):
        return str(self._to_element().pretty_string())
    
    def _to_element(self):
        if hasattr(self,'_type') and hasattr(self,'value'):
            returnelement = ioelement.IOElement(self.name,{'type':str(self._type),'value':str(self.value)})
            return returnelement
        else:
            returnelement = ioelement.IOElement(self.name,{'type':str(self.__module__) + '.' + str(type(self).__name__)})
            if hasattr(self,''.join(('_',str(type(self).__name__),'__attribs'))):
                for key,value in self.__getattribute__(''.join(('_',str(type(self).__name__),'__attribs'))).iteritems():
                    returnelement.set_attribute(key,value)
            for prop in dir(self):
                if hasattr(self.__getattribute__(prop),'_to_element'):
                    try:
                        returnelement.add(object.__getattribute__(self,prop)._to_element())
                    except: pass
            return returnelement
